package git.soulbgm.util;

import git.soulbgm.bean.BeanDefinition;
import lombok.val;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author 贺瑞杰
 * @version V1.0
 * @date 2018-10-22 11:23
 * @description Class的工具类
 */
public class ClassUtil {

    private static final char UNDERLINE = '_';
    private static final String GET = "get";
    private static final String IS = "is";
    private static final String SET = "set";

    /**
     * 获得Class的加载器
     *
     * @return Class加载器
     */
    public static ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

    /**
     * 通过class全名称加载Class
     *
     * @param className class全名称
     * @return Class对象
     */
    public static Class loadClass(String className) {
        try {
            return getClassLoader().loadClass(className);
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

    /**
     * 通过反射的方式执行getXxx()方法
     *
     * @param obj   实体对象
     * @param field 字段
     * @return 执行了getXxx()方法之后的值
     */
    public static Object executeGetMethod(Object obj, Field field) {
        if (obj == null) {
            return null;
        }
        try {
            return obj.getClass().getMethod(buildGetMethod(field.getName(), field.getType() == Boolean.class)).invoke(obj);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            return null;
        }
    }

    /**
     * 通过反射的方法执行setXxx(xx)方法
     *
     * @param obj   实体对象
     * @param field 字段
     * @param val   执行set方法的值
     * @return 成功返回true，失败false
     */
    public static boolean executeSetMethod(Object obj, Field field, Object val) {
        if (obj == null) {
            return false;
        }
        try {
            if (val.getClass() == field.getType()) {
                Method method = obj.getClass().getMethod(buildSetMethod(field.getName()), field.getType());
                method.invoke(obj, val);
                return true;
            } else {
                return false;
            }
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            return false;
        }
    }

    /**
     * 获取字段${clazz}注解
     *
     * @param field
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T extends Annotation> T getFieldAnnotation(Field field, Class<T> clazz) {
        if (field != null && clazz != null) {
            return field.getAnnotation(clazz);
        } else {
            return null;
        }
    }

    /**
     * 判断字段中是否存在${clazz}注解
     *
     * @param field
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T extends Annotation> boolean existFieldAnnotation(Field field, Class<T> clazz) {
        if (field != null && clazz != null) {
            return field.isAnnotationPresent(clazz);
        } else {
            return false;
        }
    }

    /**
     * 获取字段${clazz}注解
     *
     * @param method
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T extends Annotation> T getMethodAnnotation(Method method, Class<T> clazz) {
        if (method != null && clazz != null) {
            return method.getAnnotation(clazz);
        } else {
            return null;
        }
    }

    /**
     * 判断字段中是否存在${clazz}注解
     *
     * @param method
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T extends Annotation> boolean existMethodAnnotation(Method method, Class<T> clazz) {
        if (method != null && clazz != null) {
            return method.isAnnotationPresent(clazz);
        } else {
            return false;
        }
    }

    /**
     * 通过给字段名称构建出相应的get方法名称
     *
     * @param fieldName 字段名称
     * @return 组合之后的名称
     */
    private static String buildGetMethod(String fieldName, boolean isBoolean) {
        StringBuilder sb = new StringBuilder();
        if (isBoolean) {
            sb.append(IS);
        } else {
            sb.append(GET);
        }
        sb.append(Character.toUpperCase(fieldName.charAt(0)));
        sb.append(fieldName.substring(1));
        return sb.toString();
    }

    /**
     * 通过给字段名称构建出相应的set方法名称
     *
     * @param fieldName 字段名称
     * @return 组合之后的名称
     */
    private static String buildSetMethod(String fieldName) {
        StringBuilder sb = new StringBuilder(SET);
        sb.append(Character.toUpperCase(fieldName.charAt(0)));
        sb.append(fieldName.substring(1));
        return sb.toString();
    }

    /**
     * 是否是getter
     *
     * @param method method对象
     * @return 布尔值
     */
    public static boolean isGetter(Method method) {
        //get开头
        if (!method.getName().startsWith(GET)) {
            return false;
        }
        //参数长度不是0
        if (method.getParameterTypes().length != 0) {
            return false;
        }
        //返回值不为空
        if (void.class.equals(method.getReturnType())) {
            return false;
        }
        return true;
    }

    /**
     * 是否是setter
     *
     * @param method
     * @return
     */

    public static boolean isSetter(Method method) {
        //是否是set开头
        if (!method.getName().startsWith(SET)) {
            return false;
        }
        //是否参数长度等于1
        if (method.getParameterTypes().length != 1) {
            return false;
        }
        return true;
    }

    /**
     * 通过传入return的Class返回对应类型的默认值
     *
     * @param resultClass
     * @return
     */
    public static Object returnDefault(String resultClass) {
        switch (resultClass) {
            case "boolean":
                return false;
            case "double":
                return 0D;
            case "float":
                return 0F;
            case "int":
                return 0;
            case "long":
                return 0L;
            case "short":
                return 0;
            case "byte":
                return 0;
            default:
                return null;
        }
    }

    /**
     * 通过传入return的Class返回对应类型的默认值
     *
     * @param resultClass
     * @return
     */
    public static Object returnDefault(Class resultClass) {
        if (resultClass == boolean.class) {
            return false;
        } else if (resultClass == double.class) {
            return 0D;
        } else if (resultClass == float.class) {
            return 0F;
        } else if (resultClass == int.class) {
            return 0;
        } else if (resultClass == float.class) {
            return 0L;
        } else if (resultClass == short.class) {
            return 0;
        } else if (resultClass == byte.class) {
            return 0;
        } else {
            return null;
        }
    }

    /**
     * 通过字符串类型传入获得
     *
     * @param type
     * @return
     */
    public static Class strTypeToClass(String type) {
        if (type == null) {
            return null;
        }
        if ("int".equals(type)) {
            return int.class;
        } else if ("byte".equals(type)) {
            return byte.class;
        } else if ("long".equals(type)) {
            return long.class;
        } else if ("double".equals(type)) {
            return double.class;
        } else if ("float".equals(type)) {
            return float.class;
        } else if ("boolean".equals(type)) {
            return boolean.class;
        } else if ("char".equals(type)) {
            return char.class;
        } else if ("String".equals(type)) {
            return String.class;
        } else if ("string".equals(type)) {
            return String.class;
        } else {
            try {
                return Class.forName(type);
            } catch (ClassNotFoundException e) {
                return null;
            }
        }
    }

    public static Object typeToValue(String type, String strVal) {
        if (type == null || strVal == null) {
            return null;
        }
        if ("int".equals(type)) {
            return Integer.parseInt(strVal);
        } else if ("byte".equals(type)) {
            return Byte.parseByte(strVal);
        } else if ("long".equals(type)) {
            return Long.parseLong(strVal);
        } else if ("double".equals(type)) {
            return Double.parseDouble(strVal);
        } else if ("float".equals(type)) {
            return Float.parseFloat(strVal);
        } else if ("boolean".equals(type)) {
            return Boolean.parseBoolean(strVal);
        } else if ("char".equals(type)) {
            return strVal.charAt(0);
        } else if ("String".equals(type)) {
            return strVal;
        } else if ("string".equals(type)) {
            return strVal;
        } else {
            return strVal;
        }
    }

    public static void main(String[] args) {
        System.out.println(strTypeToClass("char"));
    }

}
